/**********************************************************************
* Filename: Campeonato.java
* Created: 2012/04/23
* @author Fernando Brito e Abreu
**********************************************************************/
package org.quasar.copaPaises.businessLayer;

import java.util.Set;
import java.util.HashSet;

public class Campeonato
{
	public static Set<Campeonato> allInstances = new HashSet<Campeonato>();
	
	private TipoCampeonato genero;
	private String nome;
	
	/**********************************************************************
	* Default constructor
	**********************************************************************/
	public Campeonato()
	{
		allInstances.add(this);
	}
	
	/**********************************************************************
	* Parameterized constructor
	* @param genero the genero to initialize
	* @param nome the nome to initialize
	**********************************************************************/
	public Campeonato(TipoCampeonato genero, String nome)
	{
		this.genero = genero;
		this.nome = nome;
		allInstances.add(this);
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the genero of the campeonato
	**********************************************************************/
	public TipoCampeonato genero()
	{
		return genero;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param genero the genero to set
	**********************************************************************/
	public void setGenero(TipoCampeonato genero)
	{
		this.genero = genero;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the nome of the campeonato
	**********************************************************************/
	public String nome()
	{
		return nome;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param nome the nome to set
	**********************************************************************/
	public void setNome(String nome)
	{
		this.nome = nome;
	}
	
	/**********************************************************************
	* ONE2MANY getter for Campeonato[1] <-> Grupo[*]
	* @return the grupos of the campeonato
	**********************************************************************/
	public Set<Grupo> grupos()
	{
		Set<Grupo> result = new HashSet<Grupo>();
		for (Grupo x : Grupo.allInstances)
			if (x.campeonato()  ==  this)
				result.add(x);
		return result;
	}
	
	/**********************************************************************
	* ONE2MANY setter for Campeonato[1] <-> Grupo[*]
	* @param grupos the grupos to set
	**********************************************************************/
	public void setGrupos(Set<Grupo> grupos)
	{
		for (Grupo x : grupos)
			x.setCampeonato(this);
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE getter for Campeonato[*] <-> Participacao[2..*]
	* @return the participacao of the participado
	**********************************************************************/
	public Set<Participacao> participacao()
	{
		Set<Participacao> result = new HashSet<Participacao>();
		for (Participacao x : Participacao.allInstances)
			if (x.participado()  ==  this)
				result.add(x);
		return result;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE setter for Campeonato[*] <-> Participacao[2..*]
	* @param participacao the participacao to set
	**********************************************************************/
	public void setParticipacao(Set<Participacao> participacao)
	{
		for (Participacao x : participacao)
			x.setParticipado(this);
	}
	
	/**********************************************************************
	* MEMBER2MEMBER getter for Campeonato[*] <-> Pais[2..*]
	* @return the participante of the participado
	**********************************************************************/
	public Set<Pais> participante()
	{
		Set<Pais> result = new HashSet<Pais>();
		for (Participacao x : Participacao.allInstances)
			if (x.participado()  ==  this)
				result.add(x.participante());
		return result;
	}
	
	/**********************************************************************
	* MEMBER2MEMBER setter for Campeonato[*] <-> Pais[2..*]
	* @param participante the participante to set
	**********************************************************************/
	public void setParticipante(Set<Pais> participante)
	{
		for (Pais t : participante)
			for (Participacao x: Participacao.allInstances)
				if (x.participado() == this)
					x.setParticipante(t);
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public void criaMembrosEquipas()
	{
		//	TODO
		//	for eq in self.grupos->collectNested($e : Grupo | $e.jogos)->flatten->collectNested($e : Jogo | $e.equipa)->flatten->asSet do eq.criaFichaJogoFalsa() end;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param jogador the jogador to set
	**********************************************************************/
	public int getCartoesJogador(Jogador jogador)
	{
		//	TODO
		//	return self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->select(j : Jogador | (j = jogador))->collectNested($e : Jogador | $e.membro)->flatten->collectNested($e : Membro | $e.cartoes)->flatten->size
		return -1;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param pais the pais to set
	**********************************************************************/
	public int getGolosEquipaCampeonato(Pais pais)
	{
		//	TODO
		//	return self.participante->select(p : Pais | (p = pais))->collectNested($e : Pais | $e.equipa)->flatten->collectNested($e : Equipa | $e.membro)->flatten->collectNested($e : Membro | $e.golos)->flatten->size
		return -1;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param jogador the jogador to set
	**********************************************************************/
	public int getGolosJogadorCampeonato(Jogador jogador)
	{
		//	TODO
		//	return self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->select(j : Jogador | (j = jogador))->collectNested($e : Jogador | $e.membro)->flatten->collectNested($e : Membro | $e.golos)->flatten->size
		return -1;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public Jogador getJogadorMaisNovo()
	{
		//	TODO
		//	return self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->select(j : Jogador | (j.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia) = self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->collectNested($e : Jogador | $e.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia))->min))
		return null;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public Jogador getJogadorMaisVelho()
	{
		//	TODO
		//	return self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->select(j : Jogador | (j.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia) = self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->collectNested($e : Jogador | $e.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia))->max))
		return null;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param jogador the jogador to set
	**********************************************************************/
	public int getMediaMinutosJogados(Jogador jogador)
	{
		//	TODO
		//	return (self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->select(j : Jogador | (j = jogador))->collectNested($e : Jogador | $e.membro)->flatten->collect(m : Membro | (m.minuto_saida - m.minuto_entrada))->sum / self.participacao->collectNested($e : Participacao | $e.plantel)->flatten->select(j : Jogador | (j = jogador))->collectNested($e : Jogador | $e.nacionalidade)->collectNested($e : Pais | $e.equipa)->flatten->size)
		return -1;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public Treinador getTreinadorMaisNovo()
	{
		//	TODO
		//	return self.participacao->collectNested($e : Participacao | $e.treinador)->select(t : Treinador | (t.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia) = self.participacao->collectNested($e : Participacao | $e.treinador)->collectNested($e : Treinador | $e.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia))->min))
		return null;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public Treinador getTreinadorMaisVelho()
	{
		//	TODO
		//	return self.participacao->collectNested($e : Participacao | $e.treinador)->select(t : Treinador | (t.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia) = self.participacao->collectNested($e : Participacao | $e.treinador)->collectNested($e : Treinador | $e.getIdade(self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first.dia))->max))
		return null;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param nome the nome to set
	* @param genero the genero to set
	* @param paises the paises to set
	* @param grupos the grupos to set
	**********************************************************************/
	public void inicializa(String nome, TipoCampeonato genero, String paises, String grupos)
	{
		//	TODO
		//	self.nome := nome;
		//	 self.genero := genero;
		//	 for p in paises do participacao := new Participacao(((p + '_') + self.nome)) between (new Pais(p),self);
		//	 participacao.organizador := false;
		//	 treinador := new Treinador(('Treinador_' + p));
		//	 insert (treinador,participacao) into Treinador_Participacao end;
		//	 for g in grupos do insert (self,new Grupo(g)) into Campeonato_Grupo end;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public void processarClassificacoes()
	{
		//	TODO
		//	Jogo_final := self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence->first;
		//	 Jogos_meiasfinais := self.grupos->select(g : Grupo | (g.fase = FaseCampeonato::MeiasFinais))->collectNested($e : Grupo | $e.jogos)->flatten->asSequence;
		//	 for m in Jogos_meiasfinais do if (m.goleadores()->collectNested($e : Jogador | $e.nacionalidade)->count(m.seleccao->first) > m.goleadores()->collectNested($e : Jogador | $e.nacionalidade)->count(m.seleccao->last)) then self.participante->select(p : Pais | (m.seleccao->last = p))->collectNested($e : Pais | $e.participacao)->flatten->asSequence->first.classificacao := 3 else self.participante->select(p : Pais | (m.seleccao->first = p))->collectNested($e : Pais | $e.participacao)->flatten->asSequence->first.classificacao := 3 end end;
		//	 if (Jogo_final.goleadores()->collectNested($e : Jogador | $e.nacionalidade)->count(Jogo_final.seleccao->first) > Jogo_final.goleadores()->collectNested($e : Jogador | $e.nacionalidade)->count(Jogo_final.seleccao->last)) then self.participante->select(p : Pais | (Jogo_final.seleccao->first = p))->collectNested($e : Pais | $e.participacao)->flatten->asSequence->first.classificacao := 1;
		//	 self.participante->select(p : Pais | (Jogo_final.seleccao->last = p))->collectNested($e : Pais | $e.participacao)->flatten->asSequence->first.classificacao := 2 else self.participante->select(p : Pais | (Jogo_final.seleccao->last = p))->collectNested($e : Pais | $e.participacao)->flatten->asSequence->first.classificacao := 1;
		//	 self.participante->select(p : Pais | (Jogo_final.seleccao->first = p))->collectNested($e : Pais | $e.participacao)->flatten->asSequence->first.classificacao := 2 end;
	}
	
	/* (non-Javadoc)
	* @see java.lang.Object#toString()
	*/
	@Override
	/**********************************************************************
	* Object serializer
	**********************************************************************/
	public String toString()
	{
		return "Campeonato [genero=" + genero + ", nome=" + nome + "]\n";
	}
	
}
